﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Dukous.Domain
{
    /// <summary>
    /// 实体抽象类
    /// </summary>
    /// <typeparam name="IdT"></typeparam>
    [Serializable]
    public abstract class Entity<IdT> : IEntity<IdT>
    {
        /// <summary>
        /// 
        /// </summary>
        public virtual IdT Id { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public virtual bool Equals(Entity<IdT> other)
        {
            if (other == null)
            {
                return false;
            }

            if (ReferenceEquals(this, other))
            {
                return true;
            }

            if (!IsTransient(this) &&
                !IsTransient(other) &&
                object.Equals(this.Id, other.Id))
            {
                var otherType = other.GetUnproxiedType();
                var thisType = this.GetUnproxiedType();
                return thisType.IsAssignableFrom(otherType) || otherType.IsAssignableFrom(thisType);
            }

            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            return Equals(obj as Entity<IdT>);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            if (object.Equals(Id, default(IdT)))
            {
                return base.GetHashCode();
            }

            return Id.GetHashCode();
        }

        private Type GetUnproxiedType()
        {
            return this.GetType();
        }

        private static bool IsTransient(Entity<IdT> obj)
        {
            return obj != null && object.Equals(obj.Id, default(IdT));
        }
    }
}
